home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Languages / Masm V6.11 / INCLUDE / CMACROS.NE$ / CMACROS
Encoding:
Text File  |  1992-03-03  |  36.8 KB  |  1,613 lines

  1. COMMENT $
  2.  
  3. CMACROS - assembly macros for interfacing to HLL
  4.  
  5. (C)Copyright Microsoft Cor. 1990
  6.  
  7. $
  8.  
  9. ; Revision History
  10. ;    6.0    Initial Release of cmacros for MASM 6.0
  11. ;
  12.  
  13. COMMENT $
  14.  
  15. ; Note:  There are some differences between this version of CMACROS
  16. ;    and previous releases.  The most signification is the fact
  17. ;    that locals and parameter names are now scoped to the body
  18. ;    of a procedure.  To help ease this problem we have introduced
  19. ;    a new directive cRet. This means that the following transformation
  20. ;    can occur on your source to deal with parameters no referenced
  21. ;    in the body of a procedure
  22. ;
  23. ;    cProc                cProc
  24. ;    locals,parms            locals,parms
  25. ;    cBegin                cBegin
  26. ;    ....                ...
  27. ;    cEnd                cRet
  28. ;    error code referencing         error code referencing
  29. ;        locals and parms        locals and params
  30. ;                    cEnd <nogen>
  31. ;
  32. ;    The major reason for making locals and parameters scoped was
  33. ;    the percieved benifit of error checking for defined labels in
  34. ;    the procedure and the addition of codeView information on locals
  35. ;    and parameters for functions.
  36.  
  37. $
  38. .xcref                    ; Get rid of alot of symbols
  39.  
  40. ;    ??_out - output the given message to the console unless ?QUIET
  41. ;        has been specified
  42. ;
  43. ;    usage:
  44. ;        ??_out <t>
  45. ;    where:
  46. ;        <t> is the message to output
  47.  
  48. ??_out macro t
  49.  ifndef ?QUIET
  50.   echo t
  51.  endif
  52. endm
  53.  
  54. ;  outif - output msg if name is non-zero.  If name is undefined,
  55. ;    set name =0, else set name to the default value.
  56. ;
  57. ;  usage:
  58. ;    outif    name, defval, onmsg, offmsg
  59. ;  where:
  60. ;    name    name of symbol
  61. ;    defval    default value to give symobl if not defined.
  62. ;            if blank, then 0 will be used
  63. ;    onmsg    text to display if symbol is non-zero
  64. ;    offmsg    text to display if symbol is zero
  65. ;
  66.  
  67. outif macro name:req, defval:=<0>, onmsg, offmsg
  68.  ifndef name
  69.   name = defval
  70.  endif
  71.  if name
  72.   name = 1
  73.   ifnb <onmsg>
  74.    ??_out <! onmsg>
  75.   endif
  76.  else
  77.   ifnb <offmsg>
  78.    ??_out <! offmsg>
  79.   endif
  80.  endif
  81. endm
  82.  
  83.  
  84. ; ??error - output message and generate an assembly time error
  85. ;
  86. ; usage:
  87. ;    ??error <t>
  88. ; where:
  89. ;    t    is the text to output
  90. ;
  91.  
  92. ??error macro msg
  93.  echo e r r o r ------ msg        ;; to console
  94.  .err e r r o r ------ msg        ;; forced error by assembler
  95. endm
  96.  
  97. ??_out <cMacros Version 6.00 - 1/1/91>
  98. ??_out <Copyright (C) Microsoft Corp. 1990-1991. All rights reserved.>
  99.  
  100. ;
  101. ; Determine the memory model for cmacros.  Default to small if
  102. ;    no other model has been specified.
  103. ;
  104.  
  105. ifdef ?SMALL
  106.  memS=1
  107. endif
  108. ifdef ?MEDIUM
  109.  memM=1
  110. endif
  111. ifdef ?COMPACT
  112.  memC=1
  113. endif
  114. ifdef ?LARGE
  115.  memL=1
  116. endif
  117. ifdef ?HUGE
  118.  memH=1
  119. endif
  120.  
  121.  
  122. outif    memS,0,<Small Model>
  123. outif    memM,0,<Medium Model>
  124. outif    memC,0,<Compact Model>
  125. outif    memL,0,<Large Model>
  126. outif    memH,0,<Huge Model>
  127.  
  128. memMOD = memS + memM + memL + memC + memH
  129. if memMOD ne 1
  130.  if memMOD eq 0
  131.   memS=1                ; Assume small model
  132.   outif    memS,0,<Small Model>
  133.  else
  134.   ??error <must have only 1 memory model selected>
  135.  endif
  136. endif
  137.  
  138. sizec = memM + memL + memH        ; Large Code models
  139. sizeC = sizec
  140. sized = memC + memL + memH        ; Large Data models
  141. sizeD = sized
  142.  
  143. ;
  144. ;  Inform user of any other options selected
  145. ;
  146.  
  147. outif    ?DF,0,<No segments or groups will be defined>
  148. outif    ?DFDATA,0,<No data segments will be defined>
  149. outif    ?DFCODE,0,<No code segments will be defined>
  150. outif    ?TF,0,<Epilogue sequences will assume valid SP>
  151. outif    ?WIN,1,<Windows support>
  152. outif    ?COW,0,<Character Windows support>
  153. outif    ?PLM,1,<PL/M calling convention>
  154. outif    ?NOATOMIC,0,<ATOMIC calling convention>
  155. outif    ?NODATA,0,<NODATA module>
  156.  
  157. ifdef ?CHKSTK
  158.  ifdef ?CHKSTKPROC
  159.   ??_out <! Private stack checking enabled>
  160.  else
  161.   ??_out <! Stack checking enabled>
  162.  endif
  163. else
  164.  ?CHKSTK = 0
  165. endif
  166.  
  167. ifndef ?DOS5
  168. ?DOS5 = 0
  169. endif
  170.  
  171. ;
  172. ; Setup some local variables to the Cmacros package
  173. ;
  174.  
  175. ??CM_state = 0            ; 0 - inactive, 1-cProc, 2-cBegin, 
  176. ??CM_RegSaveList textequ <>    ; List of saved registers
  177. ??CM_ArgList textequ <>
  178.  
  179. ;
  180. ;    This function is used to paste together two text items to
  181. ;    get a third text item.
  182. ;
  183.  
  184. ??CM_Paste macro arg1:req, arg2:req
  185.  exitm <arg1&arg2>
  186. endm
  187.  
  188. ;
  189. ;    This function is used to create a text macro containning the
  190. ;    n-th local to a fuction definition.
  191. ;
  192.  
  193. ??CM_addLocal macro arg1:req
  194.  ??CM_Paste(??CM_local, %??CM_localCount) textequ <LOCAL arg1>
  195.  ??CM_localCount = ??CM_localCount + 1
  196. endm
  197.  
  198. ;
  199. ;    This function is used to create a text macro containning the
  200. ;    n-th parameter to a function definition
  201. ;
  202.  
  203. ??CM_addParm macro arg1:req
  204.  if ??CM_argCount EQ 20
  205.   .err <CMACROS.INC: Cannot have more than 20 arguements to a procedure>
  206.  endif
  207.  ??CM_Paste(??CM_arg, %??CM_argCount) textequ <, arg1>
  208.  ??CM_argCount = ??CM_argCount + 1
  209. endm
  210.  
  211. ;
  212. ;    This macro creates the prologue code for a cmacro defined function.
  213. ;    
  214. ;    Prologue sequences
  215. ;
  216.  
  217. cPrologue macro procname, flags, cbParms, cbLocals, reglist, userparms
  218.  
  219.   ?ba=0                 ;;not in a procedure
  220.   ?pu=0                 ;;initial public setting
  221.   ?ia=0                 ;;no special prolog/epilog
  222.   ?rp=0                 ;;no register parameters
  223.   ??CM_UserDoesFrame=0            ;;don't use makeframe
  224.   ?ff=0                 ;;don't force frame setup
  225.   ?pas=0                ;;process register save list
  226.   ?pcc=?PLM                ;;calling convention (C or PL/M)
  227.  
  228.   
  229.   
  230.   ;;
  231.   ;; Look at all of the user parameters and make appropriate decisions
  232.   ;;
  233.  
  234.   for x,<userparms>
  235.     ifdef ??CM_Paste(??_cproc_, x)
  236.       ??CM_Paste(??_cproc_, x)
  237.     else
  238.       ??error <e r r o r - unknown keyword x>
  239.       .err
  240.     endif
  241.   endm
  242.   
  243.   ;;
  244.   ;; Now start some error checking
  245.   ;;
  246.  
  247.   if (??CM_Atomic eq 1) and (??CM_NoData eq 0) ;;ATOMIC requires NODATA
  248.     ??error <ATOMIC specified without NODATA - ATOMIC ignored>
  249.     ??CM_Atomic = 0                ;;clear the ATOMIC keyword
  250.   endif
  251.  
  252.   if flags AND 020h            ;;if a far procedure
  253.     if ??CM_WinFarProc            ;;if windows
  254.       ife ??CM_Atomic            ;;if not ATOMIC
  255.         ife ?COW            ;; COW dos not save DS
  256.       ?ia=2                ;;  adjust locals for saved ds
  257. ;      ?pas = ?pas and (not ?ds)    ;;no need for extra save
  258.     endif
  259.       endif
  260.     endif
  261.   else
  262.     ??CM_WinFarProc=0            ;;not a far windows procedure
  263.   endif
  264.  
  265. ; ?pas = ?pas and (not (?sp+?cs+?ss))    ;;make no sense to save these
  266.  
  267.   if ??CM_UserDoesFrame                ;;don't save these if user frame
  268. ;  ?pas = ?pas and (not (?bp+?si+?di))
  269.   endif
  270.  
  271.   if ??CM_UserDoesFrame                ;;if user frame
  272.     if ??CM_NoData
  273.       ??error <NODATA encountered in &n - user frame ignored>
  274.       ??CM_UserDoesFrame=0
  275.     endif
  276.   endif
  277.     
  278.   if ??CM_UserDoesFrame                ;;if user frame
  279.    if ?rp                ;;If register parameters
  280.     ??error <parmR encountered in &n - user frame ignored>
  281.     ??CM_UserDoesFrame=0
  282.    endif
  283.   endif
  284.    
  285.   ?cpd=0                ;;terminate current proc def
  286.     
  287.  ifidn <g>,<nogen>            ;;if nogen, then cannot have locals
  288.   if cbLocals + cbParms + ?rp    ;;  saved regs, or parmRs
  289.    ??_out <cBegin - possibly invalid use of nogen>
  290.   endif
  291.  else                    ;;else must generate a frame
  292.    
  293.   ;;
  294.   ;;  Allow the user to specify his own routine which is going to
  295.   ;;    do the frame set-up for this procedure
  296.   ;;
  297.   
  298.   if ??CM_UserDoesFrame        ;;if user frame code specified
  299.    ?mf c,cbLocals,%?po        ;;  call user's makeframe
  300.    for reg,reglist        ;;  save specified registers
  301.     push reg
  302.    endm
  303.   else
  304.  
  305.    if ??CM_WinFarProc        ;;if a far windows procedure
  306.     ife ??CM_NoData        ;;if not NODATA,
  307.      mov ax,ds             ;;   then set AX = current ds, and    ;@
  308.      nop            ;;   leave room for  MOV AX,1234h     ;@
  309.     endif
  310.  
  311.     ife ??CM_Atomic        ;;if not ATOMIC, far frame must be set
  312.      
  313.      ife ?DOS5             ;;if not DOS5, then set far frame flag
  314.       inc bp            ;;  by incrementing the old bp          ;@
  315.      endif
  316.           
  317.      push bp                                  ;@
  318.      mov bp,sp                               ;@
  319.           
  320.      ife ?COW            ;; save DS not needed for CW
  321.       push ds                                  ;@
  322.      endif
  323.       
  324.     else            ;;ATOMIC procedure
  325.         
  326.      if ?ff+cbLocals+cbParms+?rp    ;;if any locals or parameters
  327.       push bp             ;;  then must set frame pointer       ;@
  328.       mov bp,sp            ;;  to be able to access them          ;@
  329.      endif
  330.           
  331.     endif
  332.         
  333.     ife ??CM_NoData        ;;if not NODATA, then AX should
  334.      mov ds,ax             ;;  have the ds to use              ;@
  335.     endif
  336.         
  337.    else                ;;not windows.    use standard prolog
  338.       
  339.     if ?ff+cbLocals+cbParms+?rp        ;;if any locals or parameters
  340.      push bp            ;;  then must set frame pointer       ;@
  341.      mov bp,sp         ;;  to be able to access them          ;@
  342.     endif
  343.    endif
  344.     
  345.    if ?rp            ;;if parmR's, push them before
  346.     ??CM_UserDoesFrame=0            ;;  allocating locals and saving
  347.     rept ?rp            ;;  the autosave registers
  348.      uconcat mpush,,?rp,%??CM_UserDoesFrame
  349.      ??CM_UserDoesFrame=??CM_UserDoesFrame+1
  350.     endm
  351.    endif
  352.     
  353.    if cbLocals            ;;if locals to allocate
  354.     if ?CHKSTK             ;;if stack checking enabled
  355.      ifdef ?CHKSTKPROC         ;;if user supplied stack checking
  356.       ?CHKSTKPROC %cbLocals    ;;  invoke it with bytes requested
  357.      else
  358.       mov ax,cbLocals        ;;invoke default stack checking       ;@
  359.       ife cc
  360.        call _chkstk                              ;@
  361.       else
  362.        call chkstk                              ;@
  363.       endif
  364.      endif
  365.     else            ;;no stack checking
  366.      sub   sp,cbLocals    ;; allocate any local storage          ;@
  367.     endif
  368.    endif
  369.   endif
  370.    
  371.   for reg,reglist        ;;save autosave registers
  372.    push reg
  373.   endm
  374.  endif                ;; No Gen
  375.  
  376.  ifdef ?PROFILE        ;;if profiling enabled
  377.   if c                ;;  and a far procedure
  378.    call StartNMeas        ;;  invoke profile start procedure    ;@
  379.   endif
  380.  endif
  381.  
  382.  exitm %(cbLocals+?ia)
  383. endm
  384.  
  385. ;
  386. ;    This macro will define the epilogue sequences for CMACROS
  387. ;    functions.
  388. ;
  389. ;    Epilog sequences
  390.  
  391. cEpilog macro procname, flags, cbParms, cbLocals, reglist, userparms
  392.  if ??CM_nogen            ;; Nogen the cEnd --
  393.   exitm
  394.  endif
  395.  
  396.  ?ba=0                ;;no longer in a procedure
  397.  
  398.  ifidn <g>,<nogen>        ;;if nogen, then cannot have parmRs
  399.   if a+r+lc             ;;  locals, or saved registers
  400.    ??_out <cEnd - possibly invalid use of nogen>
  401.   endif
  402.  else                ;;else must remove the frame
  403.   ifdef ?PROFILE        ;;if profiling enabled
  404.    if flags AND 020H        ;;  and a far procedure
  405.     call StopNMeas        ;;  invoke profile stop procedure
  406.    endif            ;;  (doesn't trash DX:AX)
  407.   endif                ;; ?PROFILE
  408.   for reg,reglist        ;;restore autosaved registers
  409.    pop reg
  410.   endm
  411.   if ??CM_UserDoesFrame        ;;if to use the "makeframe" procedure
  412.    db 0c3h             ;;  near return to user's makeframe    @
  413.   else
  414.    if ??CM_WinFarProc        ;;if far win proc, use special epilog
  415.     ife ??CM_Atomic        ;;if not ATOMIC, bp was pushed
  416.      ife ?COW            ;; restore DS not needed for CW
  417.       if (?TF eq 0) or (cbLocals+?rp)    ;;if cannot assume valid sp
  418.        lea sp,-2+[bp]        ;;  or locals or parmR's, get valid SP @
  419.       endif
  420.       pop ds            ;;restore saved ds and bp           @
  421.      else
  422.       if (?TF eq 0) or (cbLocals+?rp)    ;;if cannot assume valid sp
  423.        mov sp,bp
  424.       endif
  425.      endif
  426.      pop BP            ;;                       @
  427.      ife ?DOS5            ;;if not DOS5, bp was
  428.       dec BP            ;;  incremented to mark far frame      @
  429.      endif
  430.     else                ;;ATOMIC frame was set up
  431.      if memS32
  432.       leave
  433.      else
  434.       if (?TF eq 0) or (cbLocals+?rp)    ;;if cannot assume valid sp
  435.        mov SP,BP         ;;  or locals or parmR's, get valid SP @
  436.       endif
  437.       if cbLocals+cbParms+?rp
  438.        pop BP                              ;@
  439.       endif
  440.      endif
  441.     endif
  442.    else                ;;non-windows standard epilog
  443.     if ?ff+cbLocals+cbParms+?rp        ;;if any parameters
  444.      if (?TF eq 0) or (cbLocals+?rp)    ;;if cannot assume valid SP
  445.       mov SP,BP         ;;  or locals or parmR's, get valid SP;@
  446.      endif
  447.      pop BP                                  ;@
  448.     endif
  449.    endif            ;; Far Win Proc
  450.    ife flags AND 010H        ;;if Pascal calling convention
  451.     ret cbParms            ;;  return and remove paramteres      ;@
  452.    else                ;;else
  453.     ret             ;;  return                   ;@
  454.    endif
  455.   endif                ;; User makes frame
  456.  endif                ;; noGen
  457. endm
  458.  
  459. ;
  460. ; cProc - This macro is used to define the start of a procedure in CMACROS.
  461. ;
  462. ; PARAMETERS:
  463. ;    pname   - The name of the procedure to be defined.  This field is
  464. ;        required to be present.
  465. ;    attribs - This is a list of attributes which may be placed on the
  466. ;        function being defined.
  467. ;    autoSave - This is an optional list of registers which are to be
  468. ;        saved and restored during the prologue/epilogue processing
  469. ;
  470.  
  471.  
  472. cProc macro pname:REQ, attribs, autoSave
  473.  
  474.  IF ??CM_state NE 0            ;; No nesting of functions allowed
  475.   .err    <CMACROS.INC: Cannot nest procedure definitions>
  476.  endif
  477.  ;
  478.  ;  Setup some state variables to start the procedure definition
  479.  ;
  480.  ??CM_state = 1                ;; Set state variable to seen cProc
  481.  ??CM_ProcName EQU <pname>
  482.  ??CM_ProcAutoSave EQU <autoSave>
  483.  ??CM_localCount = 0
  484.  ??CM_argCount = 0
  485.  ??CM_langType EQU <>
  486.  ??CM_WinFarProc=?WIN            ;;default far procedure (win or not)
  487.  ??CM_NoData=?NODATA            ;;default NODATA flag
  488.  ??CM_Atomic=?NOATOMIC             ;;default is not ATOMIC
  489.  repeat 20                ;; Clear all parameter textmacros
  490.   ??CM_Paste(??CM_arg, %??CM_argCount) textequ <>
  491.   ??CM_argCount = ??CM_argCount + 1
  492.  endm
  493.  ??CM_argCount = 0
  494.  
  495.  ife sizec                ;; Set the default distance
  496.   dist equ <NEAR>
  497.  else
  498.   dist equ <FAR>
  499.  endif
  500.  
  501.  vis equ <>                ;; Set the default visibility
  502.  
  503.  for arg,<attribs>            ;; Look at the attribute list
  504.   ifidn <arg>, <FAR>
  505.    dist equ <FAR>
  506.   elseifidn <arg>,<NEAR>
  507.    dist equ <NEAR>
  508.   elseifidn <arg>,<PUBLIC>
  509.    vis equ <PUBLIC>
  510.   elseifidn <arg>,<PRIVATE>
  511.    vis equ <PRIVATE>
  512.   elseifidn <arg>,<LOCAL>        ;; Ignore -- only for CRT
  513.   elseifidn <arg>,<PASCAL>
  514.     ??CM_langType equ <PASCAL>
  515.   elseifidn <arg>,<C>
  516.     ??CM_langType equ <C>
  517.   elseifidn <arg>,<WIN>
  518.     ??CM_WinFarProc=1
  519.   elseifidn <arg>,<NOWIN>
  520.     ??CM_WinFarProc=0        
  521.   elseifidn <arg>,<NODATA>
  522.     ??CM_NoData=1
  523.   elseifidn <arg>,<ATOMIC>
  524.     ??CM_Atomic=1
  525.   else
  526. %  .err <CMACROS.INC: cProc -- Unknown arguement '&arg'>
  527.   endif
  528.  endm
  529.  
  530.  option prologue:cPrologue        ;; Change to our prologue sequence
  531.  option epilogue:none            ;; rets from here on are just rets
  532.     
  533. endm
  534.  
  535.  
  536. ;
  537.  
  538. cBegin macro pname
  539.  local t2
  540. IF ??CM_state NE 1            ;; Must follow cProc
  541.  .err    <CMACROS.INC: cBegin must follow a cProc>
  542. endif
  543. ??CM_nogen = 0
  544. ifnb    <pname>
  545.  ifidn  <pname>,<nogen>
  546.   ??CM_nogen = 1
  547.  elseifdif    ??CM_ProcName, <pname>
  548. %  echo    <cBegin name (&pname) must match name on preceding cProc (&??CM_ProcName>
  549.  endif
  550. endif
  551.     ??CM_state = 2        ;; Seen a cBegin
  552. %    setDefLangType ??CM_langType
  553.     macroarg EQU <>
  554. ifnb    ??CM_ProcAutoSave
  555.     ??uses CATSTR <uses >, ??CM_ProcAutoSave
  556.     t2 = @InStr(, %??uses, <,>)
  557.     while t2 NE 0
  558.         ??uses CATSTR @SubStr(<%??uses>, 1, %t2-1), < >, @SubStr(<%??uses>, %t2+1)
  559.         t2 = @InStr(, %??uses, <,>)
  560.     endm
  561. else
  562.     ??uses textequ <>
  563. endif
  564. ifidn defLangType,<C>
  565. %  ??CM_Paste(_, %??CM_ProcName) textequ <??CM_ProcName>
  566. endif
  567.  
  568.  ??CM_ProcName proc dist defLangType vis macroarg ??uses ??CM_arg0 ??CM_arg1 ??CM_arg2 ??CM_arg3 ??CM_arg4 ??CM_arg5 ??CM_arg6 ??CM_arg7 ??CM_arg8 ??CM_arg9 ??CM_arg10  ??CM_arg11 ??CM_arg12 ??CM_arg13 ??CM_arg14 ??CM_arg15 ??CM_arg16 ??CM_arg17 ??CM_arg18 ??CM_arg19
  569.     ??CM_ProcAutoSave EQU <>
  570. t2 = 0
  571. repeat ??CM_localCount
  572.  ??CM_Paste(??CM_local, %t2)
  573.  t2  = t2 + 1
  574. endm
  575. endm
  576.  
  577.  
  578. ;
  579.  
  580. cEnd macro pname
  581. IF ??CM_state NE 2            ;; Must follow a cEnd
  582.  .err    <cEnd must follow a cProc>
  583. endif
  584.  
  585. ??CM_nogen = 0
  586.  
  587. ifnb    <pname>
  588.  ifidn  <pname>,<nogen>
  589.   ??CM_nogen = 1
  590.  elseifdif ??CM_ProcName, <pname>
  591. % echo    <cEnd name (&pname) must match preceeding cProc name (&??CM_ProcName)>
  592.  endif
  593. endif
  594.  
  595.  option epilogue:cEpilog
  596.  ret
  597.  option prologue:prologuedef
  598.  option epilogue:epiloguedef
  599.  ??CM_ProcName    endp
  600.  ??CM_state = 0        ;; not in a function
  601. endm
  602.  
  603. ;
  604. ;
  605.  
  606. cRet macro 
  607.  IF ??CM_state NE 2            ;; Must follow a cBegin
  608.   .err    <cRet must follow a cProc>
  609.  endif
  610.  
  611.  option epilogue:cEpilog
  612.  ret
  613.  option epilogue:none
  614. endm
  615.  
  616.  
  617. ;
  618. ; createSeg is a macro that sets up a segment definition and
  619. ;    a logical name for that segment.  The logical name can
  620. ;    be used to egner the segment, but it cannot be used for anyting
  621. ;    else.
  622. ;
  623. ;    usage:
  624. ;        createSeg n, ln, a, co, cl, grp
  625. ;    where:
  626. ;        n    is the physical name of the segment
  627. ;        ln    is the name it is to be invoked by
  628. ;        a    is the alignment, and is optional
  629. ;        co    is the combine type, and is optional
  630. ;        cl    is the class, and is optional
  631. ;        grp    is the name of the group that contains the segment
  632. ;
  633.  
  634. createSeg macro segName, logName, aalign, combine, class, grp
  635.   ifnb <class>
  636.     segName segment aalign combine '&class'
  637.   else
  638.     segName segment aalign combine
  639.   endif
  640.   segName ends
  641.   ifnb <grp>
  642.         grp GROUP segName
  643.     logName&OFFSET    equ    offset grp:
  644.     logName&BASE    equ    grp
  645.   else
  646.     logName&OFFSET    equ    offset segName:
  647.     logName&BASE    equ    segName
  648.   endif
  649.  
  650.   logName&_sbegin macro
  651.     segName    segment
  652.     sEnd macro name
  653.         ifnb <name>
  654.          ifdifi <name>,<logName>
  655. %          echo <sEnd name does not match sBegin logName>
  656.          endif
  657.         endif
  658.         segName ends
  659.         purge sEnd
  660.     endm
  661.   endm
  662.   
  663.   ifnb <grp>
  664.    logName&_assumes macro s
  665.     assume    s:grp
  666.    endm
  667.   else
  668.    logName&_assumes macro s
  669.     assume    s:segName
  670.    endm
  671.   endif
  672. endm
  673.  
  674. sBegin macro name:req
  675.  name&_sbegin
  676. endm
  677.  
  678. ;    assumes is a macro that will set up the assumes for a segment
  679. ;    or group created with the createSeg macro.  If the assumed
  680. ;    value passed in isn't known, then a normal assume is made.
  681. ;
  682. ;       usage:
  683. ;               assumes s,g
  684. ;
  685. ;       where:
  686. ;               s       is the register to make the assumption about
  687. ;               g       is the value to assume is in it
  688.  
  689.  
  690. assumes macro   s,ln
  691.   ifndef ln&_assumes
  692.     assume s:ln
  693.   else
  694.     ln&_assumes s
  695.   endif
  696. endm
  697.  
  698. ;
  699. ; defGrp
  700. ;
  701.  
  702. defGrp macro foo:vararg
  703. endm
  704.  
  705. ; setDefLangType
  706.  
  707.  
  708. setDefLangType macro overLangType
  709. ifnb <overLangType>
  710.  ifidn <overLangType>,<C>
  711.   defLangType textequ <C>
  712.  elseifidn <overLangType>,<PASCAL>
  713.   defLangType textequ <PASCAL>
  714.  elseifidn <overLangType>,<PLM>
  715.   defLangType textequ <PASCAL>
  716.  else
  717. %  .err <Illegal Language Type specified 'overLangType'>
  718.  endif
  719. else ; !nb <overLangType>
  720.  if ?PLM EQ 1
  721.   defLangType textequ <PASCAL>
  722.  elseif ?PLM EQ 0
  723.   defLangType textequ <C>
  724.  else 
  725.   .err <Illegal value for ?PLM>
  726.  endif
  727. endif ; nb <overLangType>
  728. endm
  729.  
  730.  
  731. ifndef ?NOSTATIC
  732.  
  733. .xcref
  734. .xcref staticB, staticW, staticD, staticQ, staticT, staticCP, staticDP, staticI
  735. .cref
  736.  
  737. ; staticX - define static data of type X
  738. ;
  739. ; usage:
  740. ;    staticX  n, i, s
  741. ;
  742. ; where:
  743. ;    X    is the type of the variable: b=byte, w=word, d=dword
  744. ;            q=quad word, t=ten bytes, cp=code pointer,
  745. ;            dp=data pointer, i=int
  746. ;    n    is the name of the given variable
  747. ;    i    is the initial value of the variable
  748. ;    s    is the duplication factor
  749. ;
  750. ; statics are always pascal symbols and non-public.  If they are required
  751. ;    to be public then globalX should be used.
  752.  
  753. staticB macro name:req, initVal:=<?>, repCount
  754.  ifnb <repCount>
  755.     name db repCount dup (initVal)
  756.  else
  757.     name db initVal
  758.  endif
  759. endm
  760.  
  761. staticW macro name:req, initVal:=<?>, repCount
  762.  ifnb <repCount>
  763.     name dw repCount dup (initVal)
  764.  else
  765.     name dw initVal
  766.  endif
  767. endm
  768.  
  769. staticD macro name:req, initVal:=<?>, repCount
  770.  ifnb <repCount>
  771.     name dd repCount dup (initVal)
  772.  else
  773.     name dd initVal
  774.  endif
  775. endm
  776.  
  777. staticI macro name:req, initVal:=<?>, repCount
  778.  ifnb <repCount>
  779.     name asmI repCount dup (initVal)
  780.  else
  781.     name asmI initVal
  782.  endif
  783. endm
  784.  
  785. staticQ macro name:req, initVal:=<?>, repCount
  786.  ifnb <repCount>
  787.     name dq repCount dup (initVal)
  788.  else
  789.     name dq initVal
  790.  endif
  791. endm
  792.  
  793. staticT macro name:req, initVal:=<?>, repCount
  794.  ifnb <repCount>
  795.     name dt repCount dup (initVal)
  796.  else
  797.     name dt initVal
  798.  endif
  799. endm
  800.  
  801. if sizec
  802.  staticCP macro name:req, i, s
  803.   staticD name,<i>,<s>
  804.  endm
  805. else
  806.  staticCP macro name:req, i, s
  807.   staticW name,<i>,<s>
  808.  endm
  809. endif
  810.  
  811. if sized
  812.  staticDP macro name:req, i, s
  813.   staticD name,<i>,<s>
  814.  endm
  815. else
  816.  staticDP macro name:req, i, s
  817.   staticW name,<i>,<s>
  818.  endm
  819. endif
  820.  
  821. endif ; ?NOSTATIC
  822.  
  823.  
  824. globalB macro name:req, initVal:=<?>, repCount, langType
  825.  ??CM_gbl1 name, langType, initVal, repCount, DB
  826. endm
  827.  
  828. globalW macro name:req, initVal:=<?>, repCount, langType
  829.  ??CM_gbl1 name, langType, <initVal>, repCount, DW
  830. endm
  831.  
  832. globalD macro name:req, initVal:=<?>, repCount, langType
  833.  ??CM_gbl1 name, langType, <initVal>, repCount, DD
  834. endm
  835.  
  836. globalQ macro name:req, initVal:=<?>, repCount, langType
  837.  ??CM_gbl1 name, langType, initVal, repCount, DQ
  838. endm
  839.  
  840. globalT macro name:req, initVal:=<?>, repCount, langType
  841.  ??CM_gbl1 name, langType, initVal, repCount, DT
  842. endm
  843.  
  844. if sizec
  845.  globalCP macro n,i,s,c
  846.   globalD <n>,<i>,<s>,<c>
  847.  endm
  848. else
  849.  globalCP macro n,i,s,c
  850.   globalW <n>,<i>,<s>,<c>
  851.  endm
  852. endif
  853.  
  854. if sized
  855.  globalDP macro n,i,s,c
  856.   globalD <n>,<i>,<s>,<c>
  857.  endm
  858. else
  859.  globalDP macro n,i,s,c
  860.   globalW <n>,<i>,<s>,<c>
  861.  endm
  862. endif
  863.  
  864.  
  865. ??CM_gbl1 macro name, langType, initVal, repCount:=<1>, kind
  866.  setDefLangType langType
  867.  ifidn defLangType,<C>
  868.   public _&name
  869.   name textequ <_&name>
  870.   _&name kind repCount dup (initVal)
  871.  else
  872.   public name
  873.   name kind repCount dup (initVal)
  874.  endif
  875. endm
  876.  
  877.  
  878. ifndef ?NOEXTERN
  879. .xcref
  880. .xcref externB, externW, externD, externQ, externT
  881. .xcref externNP, externFP, externP, externCP, externDP, externA
  882. .cref
  883.  
  884. ; externX - define external data of type X
  885. ;
  886. ; usage:
  887. ;    externX n,c
  888. ;
  889. ; where:
  890. ;    X    is the type of the variable: b=byte, w=word, d=dword
  891. ;            q=qword, t=tbyte, cp=code pointer, dp=data pointer
  892. ;            a=absolute, i=int
  893. ;    n    is a list of names to be defined
  894. ;    c    is the lanague convention.  C for C or PASCAL or PLM for
  895. ;        pascal.  The default (?PLM flag) will be used if not specified
  896.  
  897. externA macro names:req, langtype
  898.  ??CM_ex1 <names>, langtype, ABS
  899. endm
  900.  
  901. externB macro names:req, langtype
  902.  ??CM_ex1 <names>, langtype, BYTE
  903. endm
  904.  
  905. externW macro names:req, langtype
  906.  ??CM_ex1 <names>, langtype, WORD
  907. endm
  908.  
  909. externD macro names:req, langtype
  910.  ??CM_ex1 <names>, langtype, DWORD
  911. endm
  912.  
  913. externQ macro names:req, langtype
  914.  ??CM_ex1 <names>, langtype, QWORD
  915. endm
  916.  
  917. externT macro names:req, langtype
  918.  ??CM_ex1 <names>, langtype, TBYTE
  919. endm
  920.  
  921. externNP macro names:req, langtype
  922.  ??CM_ex1 <names>, langtype, NEAR
  923. endm
  924.  
  925. externFP macro names:req, langtype
  926.  ??CM_ex1 <names>, langtype, FAR
  927. endm
  928.  
  929. if sizec
  930.  externP macro n,c
  931.   externFP <n>,c
  932.  endm
  933.  externCP macro n,c
  934.   externD <n>,c
  935.  endm
  936. else
  937.  externP macro n,c
  938.   externNP <n>,c
  939.  endm
  940.  externCP macro n,c
  941.   externW <n>,c
  942.  endm
  943. endif
  944.  
  945. if sized
  946.  externDP macro n,c
  947.   externD <n>,c
  948.  endm
  949. else
  950.  externDP macro n,c
  951.   externW <n>,c
  952.  endm
  953. endif
  954.  
  955. ??CM_ex1 macro names, langType, kind
  956.  setDefLangType langType
  957.  for name,<names>
  958.   ifidn defLangType,<C>
  959.    name textequ ??CM_Paste(_, name)
  960.    extern ??CM_Paste(_, name):kind
  961.   else
  962.    extern defLangType name:kind
  963.   endif
  964.  endm
  965. endm 
  966.  
  967. endif  ; ?NOEXTERN
  968.  
  969. ifndef ?NOLABEL
  970.  
  971. ; labelX - define label of data type X
  972. ;
  973.  
  974. labelB macro names:req,langType
  975.  ??CM_lb1 <names>, langType, BYTE
  976. endm
  977.  
  978. labelW macro names:req,langType
  979.  ??CM_lb1 <names>, langType, WORD
  980. endm
  981.  
  982. labelD macro names:req,langType
  983.  ??CM_lb1 <names>, langType, DWORD
  984. endm
  985.  
  986. labelQ macro names:req,langType
  987.  ??CM_lb1 <names>, langType, QWORD
  988. endm
  989.  
  990. labelT macro names:req,langType
  991.  ??CM_lb1 <names>, langType, TBYTE
  992. endm
  993.  
  994. labelNP macro names:req,langType
  995.  ??CM_lb1 <names>, langType, NEAR
  996. endm
  997.  
  998. labelFP macro names:req,langType
  999.  ??CM_lb1 <names>, langType, FAR    
  1000. endm
  1001.  
  1002. if sizec
  1003.  labelP macro n,c
  1004.   labelFP <n>,c
  1005.  endm
  1006.  labelCP macro n,c
  1007.   labelD <n>,c
  1008.  endm
  1009. else
  1010.  labelP macro n,c
  1011.   labelNP <n>,c
  1012.  endm
  1013.  labelCP macro n,c
  1014.   labelW <n>,c
  1015.  endm
  1016. endif
  1017.  
  1018. if sized
  1019.  labelDP macro n,c
  1020.   labelD <n>,c
  1021.  endm
  1022. else
  1023.  labelDP macro n,c
  1024.   labelW <n>,c
  1025.  endm
  1026. endif
  1027.  
  1028. ??CM_lb1 macro names:req, langType, kind
  1029.  setDefLangType langType
  1030.  ?pu = 0
  1031.  for name,<names>
  1032.   ifidn <name>,<PUBLIC>
  1033.    ?pu =1 
  1034.   else
  1035.    ifidn defLangType,<C>
  1036.     if ?pu
  1037.      public ??CM_Paste(_, name)
  1038.     endif
  1039.     name textequ ??CM_Paste(_, name)
  1040.     ??CM_Paste(_, name) label kind
  1041.    else
  1042.     if ?pu
  1043.      public name
  1044.     endif
  1045.     name label kind
  1046.    endif
  1047.   endif
  1048.  endm
  1049. endm
  1050.  
  1051. endif ; ?NOLABEL
  1052.  
  1053.  
  1054. ifndef ?NODEF
  1055.  
  1056. ; defX - inform the macros that name is of type X
  1057. ;
  1058. ; The given name(s) is flagged to be of the given type.
  1059. ;
  1060. ; This macro is no longer needed.
  1061. ;
  1062.  
  1063. for lbl,<defB, defW, defD, defQ, defT, defCP, defDP>
  1064.  lbl macro names:req
  1065.  endm
  1066. endm
  1067.  
  1068. endif ; ?NODEF
  1069.  
  1070.  
  1071. ifndef ?NOPTR
  1072.   ;;    regPtr generates information allowing a 32-bit pointer currently
  1073.   ;;    in a register to be pushed as a parameter to a subroutine using
  1074.   ;;    the cCall macro.
  1075.   ;;
  1076.   ;;    usage:
  1077.   ;;        regptr    n,s,o
  1078.   ;;    where:
  1079.   ;;        n    is the name the argument will be known as
  1080.   ;;        s    is the register containing the segment portion
  1081.   ;;            of the pointer
  1082.   ;;        o    is the register containing the offset portion
  1083.   ;;            of the pointer
  1084.   ;;
  1085.   ;;    2/14/85 - made obsolete with farptr
  1086.  
  1087.   regPtr macro n,s,o
  1088.     farPtr n,s,o
  1089.   endm
  1090.  
  1091.  
  1092.  
  1093.   ;;    farPtr generates information allowing a 32-bit pointer to be
  1094.   ;;    pushed as a parameter to a subroutine using the cCall macro.
  1095.   ;;
  1096.   ;;    usage:
  1097.   ;;        farptr    n,s,o
  1098.   ;;    where:
  1099.   ;;        n    is the name the argument will be known as
  1100.   ;;        s    is the segment portion of the pointer
  1101.   ;;        o    is the offset portion of the pointer
  1102.   ;;
  1103.   ;;    Note that any cast must have been made in the argument itself
  1104.   ;;    (i.e. regptr ptr1,ds,<word ptr 3[si]>)
  1105.  
  1106.  
  1107.   farPtr macro n,s,o
  1108.     n macro
  1109.       push s
  1110.       push o
  1111.     endm
  1112.   endm
  1113. endif    ; ?NOPTR
  1114.  
  1115.  
  1116.  
  1117. ;;    arg - declare arguements
  1118. ;;
  1119. ;;    The given arguments(s) is added to the argument list structure
  1120. ;;
  1121. ;;    format:
  1122. ;;        arg    a
  1123. ;;
  1124. ;;    where:
  1125. ;;        a    is any valid arugment(s) to push
  1126. ;;
  1127. ;;    If any element in arglist has not been defined or isn't 16-bit
  1128. ;;    register, then a compilete specification must have been given in
  1129. ;;    a text equate and a defx also given (if not, you'll pay the penalty!)
  1130. ;;
  1131.  
  1132. arg macro args
  1133.  ifnb <args>
  1134.   ifnb ??CM_ArgList
  1135.    ??CM_ArgList textequ ??CM_ArgList, <,>, <args>
  1136.   else
  1137.    ??CM_ArgList textequ <args>
  1138.   endif
  1139.  endif
  1140. endm
  1141.  
  1142. ;;    ?CM_IsIdent - is the arguement a legal identifier?
  1143. ;;
  1144. ;;
  1145. ;; Need to enforce the following additional rules:
  1146. ;;    Digit may not be first character
  1147. ;;    Assorted other characters may be used
  1148. ;;    Dot may be the first character
  1149.  
  1150. ?CM_IsIdent macro name:REQ
  1151.  LOCAL result
  1152.  result = 1
  1153.  forc char,<name>
  1154.   if ('A' LE '&char') AND ('&char' LE 'Z')
  1155.    goto next
  1156.   endif
  1157.   if ('a' LE '&char') AND ('&char' LE 'z')
  1158.    goto next
  1159.   endif
  1160.   if ('0' LE '&char') AND ('&char' LE '9')
  1161.    goto next
  1162.   endif
  1163.   result = 0
  1164.   exitm
  1165. :next
  1166.  endm
  1167.  exitm %result
  1168. endm
  1169.  
  1170.  
  1171. ;;    @reverse
  1172. ;;
  1173.  
  1174. @reverse macro list
  1175.  LOCAL newlist
  1176.  newlist textequ <>
  1177.  for x,<list>
  1178.   newlist catstr <x>, <,>, newlist
  1179.  endm
  1180.  ifnb newlist
  1181.   newlist substr newlist, 1, @sizestr(%newlist)-1
  1182.  endif
  1183.  exitm newlist
  1184. endm
  1185.  
  1186.  
  1187. ;;    ?ap - process arguments and place onto stack
  1188. ;;
  1189. ;;    The given argument is processed (type checking) and placed
  1190. ;;    on the stack for a pending call.  There must be a type
  1191. ;;    definition for all arguments (except words).  This can be
  1192. ;;    done using text equates and the defx macro.
  1193. ;;
  1194.  
  1195. ?ap macro n
  1196.  ?argl=?argl+2                ;; assume one word is pushed
  1197.  if 0 EQ (OPATTR n)
  1198.   if ?CM_IsIdent(n)
  1199.    ifdef n
  1200.     n
  1201.     exitm
  1202.    endif
  1203.   endif
  1204. % .err <'&n' is not valid to push>
  1205.   exitm
  1206.  else
  1207.   i = (TYPE n)
  1208.   if i EQ 1                ;; byte type
  1209.    push    word ptr(n)
  1210.    exitm
  1211.   endif  
  1212.  
  1213.   if i EQ 2                ;; word type
  1214.    push    n
  1215.    exitm
  1216.   endif
  1217.  
  1218.   if i EQ 4                ;; dword type
  1219.    push word ptr (n)[2]
  1220.    push word ptr (n)
  1221.    ?argl=?argl+2
  1222.    exitm
  1223.   endif
  1224.  
  1225.   if i EQ 8                ;; qword type
  1226.    push word ptr (n)[6]
  1227.    push word ptr (n)[4]
  1228.    push word ptr (n)[2]
  1229.    push word ptr (n)
  1230.    ?argl=?argl+6
  1231.    exitm
  1232.   endif
  1233.   
  1234.   push word ptr (n)            ;; variable storage
  1235.   exitm
  1236.  endif
  1237. endm
  1238.  
  1239.  
  1240. ;;    cCall - call a 'c' language procedure
  1241. ;;
  1242. ;;    The given procedure is called with the given parameters.  If the
  1243. ;;    calling convention is C, the arguments are pushed in reverse order,
  1244. ;;    and removed after the called procedure returns.  If the calling
  1245. ;;    convention is PL/M, the arguments are pushed as they were encountered,
  1246. ;;    and the called procedure is assumed to have removed them
  1247. ;;    from the stack.
  1248. ;;
  1249. ;;    The calling convention priority will be:
  1250. ;;        1) that specified on the cCall if present,
  1251. ;;        2) that defined by the target,
  1252. ;;        3) the default (?PLM flag).
  1253. ;;
  1254. ;;    format:
  1255. ;;        cCall    n,<a>,c
  1256. ;;
  1257. ;;    where:
  1258. ;;        n    is the name of the procedure to call
  1259. ;;        a    are the arguments to be pushed (optional, may be specified
  1260. ;;        with the "arg" macro.
  1261. ;;        c    is the calling convention, C for C, PLM or PASCAL for
  1262. ;;        PL/M.  The default (?PLM flag) will be used if
  1263. ;;        not specified).
  1264. ;;
  1265.  
  1266. cCall    macro name:req,args,langType
  1267.  
  1268.  ifnb    <args>                ;; add any passed in arguments
  1269.     arg    <args>            ;;   to the list of arguments
  1270.  endif                    ;;   for this procedure
  1271.  
  1272.  ifnb    ??CM_RegSaveList                ;; If there are any resgisters
  1273. %    for reg,<??CM_RegSaveList>            ;;   to be saved across the call
  1274.         push    reg        ;;   save then on the stack
  1275.     endm                ;;
  1276.  endif                    ;;
  1277.  
  1278.  ifnb    <langType>            ;; If a lang type was specified then
  1279.   setDefLangType langType        ;;   it overrides all common sense
  1280.  else
  1281.   i = ((OPATTR name) SHR 8) AND 7    ;; Get the lang type from the symbol
  1282.   if i EQ 0                ;; No lang type ---
  1283.    setDefLangType            ;;   Use the default lang type
  1284.   elseif i EQ 1                ;; C lang type
  1285.    defLangType textequ <C>        ;;
  1286.   elseif i EQ 4                ;; Pascal Lang Type
  1287.    defLangType textequ <PASCAL>        ;;
  1288.   else                    ;; Unknown lang type
  1289.    .err <Unknown lang type specfied for '&name'> ;;
  1290.   endif
  1291.  endif
  1292.  
  1293.  ifidn defLangType,<C>            ;; If using C calling convention
  1294.   ??CM_ArgList textequ @reverse(%??CM_ArgList)    ;; then reverse the arguements
  1295.  endif                    ;;
  1296.  
  1297.  ?argl=0                ;; Clear arguement byte count
  1298.  
  1299. % for arg,<??CM_ArgList>            ;; Push the procedures arguements
  1300.   ?ap <arg>                ;;   onto the stack.  ?ap takes
  1301.  endm                    ;;   care of sizing arguements
  1302.  
  1303.  call name                ;; Do the actual call
  1304.  
  1305.  ifidn defLangType,<C>            ;; If this is a C proc and there
  1306.   if ?argl NE 0                ;;
  1307.    add sp,?argl                ;;   are parameters then pop them
  1308.   endif                    ;;   off the stack
  1309.  endif                    ;;
  1310.  
  1311.  ifnb    ??CM_RegSaveList                ;; If there were any saved registers
  1312.   ??CM_RegSaveList textequ @reverse(%??CM_RegSaveList)        ;;   then pop them off the stack
  1313. %  for reg,<??CM_RegSaveList>            ;;   at this point.
  1314.    pop    reg                ;;
  1315.   endm                    ;;
  1316.  endif                    ;;
  1317.  
  1318.  ??CM_RegSaveList textequ    <>            ;; Clear out the global state
  1319.  ??CM_ArgList textequ <>            ;;   variable used by the cCall macro
  1320. endm
  1321.  
  1322.  
  1323.  
  1324. ;;    save - flag that the indicated registers are to be saved/restored
  1325. ;;        on the next cCall invocation
  1326. ;;
  1327. ;;    usage:
  1328. ;;        save <r>
  1329. ;;
  1330. ;;    where:
  1331. ;;        r is the list of registers to be saved.
  1332. ;;
  1333. ;;    the macro generates a value for the variable ??CM_RegSaveList
  1334. ;;
  1335.  
  1336. save macro r
  1337.  ??CM_RegSaveList textequ <r>
  1338. endm
  1339.  
  1340. ;;    parmX - generate reference to parameter(s) on the stack
  1341. ;;
  1342. ;;    usage:
  1343. ;;        parmX    n
  1344. ;;    where:
  1345. ;;        x    is the type of the argument(s) b=byte, w=word, d=dword
  1346. ;;        n    is the name(s) to be given the parmeter(s).
  1347. ;;
  1348. ;;    Byte are considered to be two bytes long for alignment.
  1349. ;;
  1350. ;;    The parmd form of the macro generates two equates:
  1351. ;;
  1352. ;;        off_name  -    for accessing the offset (lsw) of the parameter
  1353. ;;        seg_name  -    for accessing the segment (msw) of the parameter
  1354. ;;
  1355.  
  1356. parmB macro names:req
  1357.  for name,<names>
  1358.   ??CM_addParm <&name:BYTE>
  1359.  endm
  1360. endm
  1361.  
  1362. parmW macro names:req
  1363.  for name,<names>
  1364.   ??CM_addParm <&name:WORD>
  1365.  endm
  1366. endm
  1367.  
  1368. parmD macro names:req
  1369.  for name,<names>
  1370.   ??CM_addParm <&name:DWORD>
  1371.   ??CM_Paste(off_, name) textequ <word ptr name[0]>
  1372.   ??CM_Paste(seg_, name) textequ <word ptr name[2]>
  1373.  endm
  1374. endm
  1375.  
  1376. parmQ macro names:req
  1377.  for name,<names>
  1378.   ??CM_addParm <&name:QWORD>
  1379.  endm
  1380. endm
  1381.  
  1382. parmT macro names:req
  1383.  for name,<names>
  1384.   ??CM_addParm <&name:TBYTE>
  1385.  endm
  1386. endm
  1387.  
  1388. if sizec
  1389.   parmCP macro n
  1390.     parmD <n>
  1391.   endm
  1392. else
  1393.   parmCP macro n
  1394.     parmW <n>
  1395.   endm
  1396. endif
  1397.  
  1398. if sized
  1399.   parmDP macro n
  1400.     parmD <n>
  1401.   endm
  1402. else
  1403.   parmDP macro n
  1404.     parmW <n>
  1405.   endm
  1406. endif
  1407.  
  1408.  
  1409. if 0
  1410. ;;    parmR - register parameter
  1411. ;;
  1412. ;;    parmR is the macro used for generating register parameters.
  1413. ;;    The space allocated for the register parameters will be
  1414. ;;      the ?ia (interface adjust) area which is between the  old
  1415. ;;    BP and the first parameter.  Normally this is empty (?ia=0),
  1416. ;;      or has the saved ds for a windows far procedure.
  1417. ;;
  1418. ;;    Byte and dword register parameters will be allowed.
  1419. ;;
  1420. ;;      usage:
  1421. ;;        parmR    n,r,r2
  1422. ;;      where:
  1423. ;;              n       is the name of the parameter
  1424. ;;              r       is the register it is in
  1425. ;;              r2      is the offset register if a dword
  1426.  
  1427.  
  1428. ifndef ?NOPARMR
  1429.   .xcref
  1430.   .xcref ?pr,parmR
  1431.   .cref
  1432.  
  1433.   parmR macro n,r,r2
  1434.     ?pr n,r,r2,%?rp,%(?ia+2)
  1435.   endm
  1436.  
  1437.   ;;    ?pr - register parameter
  1438.   ;;
  1439.   ;;    ?pr is the actual macro for generating the equates for
  1440.   ;;    register parameters.
  1441.   ;;
  1442.   ;;    usage:
  1443.   ;;        parmR    n,r,r2,i,o
  1444.   ;;    where:
  1445.   ;;        n    is the name of the parameter
  1446.   ;;        r    is the register it is in
  1447.   ;;        r2    is the offset register if a dword
  1448.   ;;        i    is the index of the ?rp to generate
  1449.   ;;        o    is the offset from bp where the parm will be
  1450.  
  1451.   ?pr macro n,r,r2,i,o
  1452.     .xcref
  1453.     ifnb <r2>                ;;if a dword parameter
  1454.       parmR seg_&n,r            ;;define segment equate
  1455.       parmR off_&n,r2            ;;define offset  equate
  1456.       n equ (dword ptr [bp-o-2])    ;;define dword equate
  1457.       .xcref ?t&n
  1458.       ?t&n=4                ;;show a dword to cmacros
  1459.     else
  1460.       .xcref ?rp&i
  1461.       ?rp&i=0                ;;show no register(s)
  1462.       ifdef ?&r             ;;define register if valid
  1463.     ?rp&i=?&r
  1464.       endif
  1465.  
  1466.       if ??? or (?cpd eq 0) or (?rp&i eq 0)
  1467.     ??error <invalid parmR encountered: &n,&r>
  1468.     exitm
  1469.       endif
  1470.  
  1471.       n equ (word ptr [bp-o])        ;;assume a word register
  1472.       ?t&n=2                ;;show a word to cmacros
  1473.       irp x,<bh,ch,dh,bl,cl,dl,ah,al>
  1474.     if ?&&x eq ?&r            ;;if really a byte register
  1475.       n equ (byte ptr [bp-o])    ;;  then make it a byte
  1476.       ?t&n=1            ;;show a byte to cmacros
  1477.       exitm
  1478.     endif
  1479.       endm
  1480.       ?ia=?ia+2             ;;show this guy is out there
  1481.       ?rp=?rp+1             ;;show one more register parameter
  1482.     endif
  1483.     .cref
  1484.   endm
  1485. endif
  1486. endif
  1487.  
  1488. localB macro name
  1489.  ??CM_addLocal ??CM_Paste(name, <:BYTE>)
  1490. endm
  1491.  
  1492. localW macro name
  1493.  ??CM_addLocal ??CM_Paste(name, <:WORD>)
  1494. endm
  1495.  
  1496. localD macro name
  1497.  ??CM_addLocal ??CM_Paste(name, <:DWORD>)
  1498.   off_&name textequ <word ptr name[0]>
  1499.   seg_&name textequ <word ptr name[2]>
  1500. endm
  1501.  
  1502. localQ macro name
  1503.  ??CM_addLocal ??CM_Paste(name, <:QWORD>)
  1504. endm
  1505.  
  1506. localT macro name
  1507.  ??CM_addLocal ??CM_Paste(name, <:TBYTE>)
  1508. endm
  1509.  
  1510. if sizec
  1511.   localCP macro n
  1512.     localD <n>
  1513.   endm
  1514. else
  1515.   localCP macro n
  1516.     localW <n>
  1517.   endm
  1518. endif
  1519.  
  1520. if sized
  1521.   localDP macro n
  1522.     localD <n>
  1523.   endm
  1524. else
  1525.   localDP macro n
  1526.     localW <n>
  1527.   endm
  1528. endif
  1529.  
  1530. localV macro name,a
  1531.  local t1
  1532.  t1 catstr <name>, < [>, %a, <]:BYTE>
  1533. % ??CM_addLocal <t1>
  1534. endm
  1535.  
  1536.  
  1537. ife ?DF
  1538. ;;
  1539. ;;    Define all segments that will be used.  This will allow the
  1540. ;;    assume and groups to be set up at one given place, and also
  1541. ;;    allow quick changes to be made
  1542. ;;
  1543.  
  1544. createSeg _TEXT,Code,word,public,CODE
  1545. ife ?NODATA
  1546.  createSeg _DATA,Data,word,public,DATA,DGROUP
  1547. endif
  1548. endif
  1549.  
  1550. ;       errnz exp - generate error message if expression isn't zero
  1551. ;
  1552. ;    The errnz will generate an error message if the expression "exp"
  1553. ;    does not evaluate to zero.  This macro is very useful for testing
  1554. ;       relationships between items, labels, and data that was coded into
  1555. ;       an application.
  1556. ;
  1557. ;                  errnz   <offset $ - offset label>   ;error if not at "label"
  1558. ;                  errnz   <eofflag and 00000001b>     ;eofflag must be bit 0
  1559. ;
  1560. ;    For expressions involving more than one token, the angle brackets
  1561. ;       must be used.
  1562. ;
  1563. ;    The macro is only evaluated on pass 2, so forward references may be
  1564. ;       used in the expression.
  1565.  
  1566. errnz macro x            ;;display error if expression is <>0
  1567.  .errnz x
  1568. endm
  1569.  
  1570. ;       errn$ label,exp - generate error message if label (exp) <> $
  1571. ;
  1572. ;    The errnz will generate an error message if the label and "exp"
  1573. ;       does not evaluate to the current value of the location counter.
  1574. ;    This macro is very useful for testing relationships between
  1575. ;       labels and the location counter that was coded into an application.
  1576. ;
  1577. ;       examples:  errn$   label        ;error if not at "label"
  1578. ;                  errn$   label,+3     ;error if not three bytes from "label"
  1579. ;                  errn$   label,-3     ;error if not three bytes past "label"
  1580. ;
  1581. ;    If no "exp" is given, it is the same as specifying 0
  1582. ;
  1583. ;    The macro is only evaluated on pass 2, so forward references may be
  1584. ;       used in the expression.
  1585.  
  1586. errn$ macro l,x             ;;error if <$-label1 (exp2)> <>0
  1587.   errnz   <offset $ - offset l x>
  1588. endm
  1589.  
  1590. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  1591.  
  1592.  
  1593. ; Extra macros for the c-runtime package
  1594. ;
  1595. ; Macro for calling another run-time-library function.
  1596. ; Does a PUSH CS/CALL NEAR in compact/large models, except
  1597. ; for QuickC.        --PHG, 5-24-89
  1598.  
  1599. callcrt MACRO    funcname
  1600. ifdef _QC2
  1601.     call    funcname
  1602. else
  1603.   if sizeC
  1604.     push    cs
  1605.     call    near ptr (funcname)
  1606.   else
  1607.     call    funcname
  1608.   endif
  1609. endif
  1610. ENDM
  1611.  
  1612. .cref                    ; Permit symbols to be listed again
  1613.